import time as lib_time

from django.db import transaction
from django.utils.translation import gettext as _

from core import errors
from apps.app_users.models import UserProfile
from apps.app_tx_meeting.models import MeetingReservation, MeetingReservationLog
from apps.app_tx_meeting.managers import MeetingReservationManager, MeetingUserWrapper
from apps.app_tx_meeting.helpers import MeetReservationHelper


class CancelReservationHandler:
    tx_room_helper = MeetReservationHelper()

    @staticmethod
    def get_has_perm_reservation(reservation_id: str, operator: UserProfile, is_as_admin: bool) -> MeetingReservation:
        """
        查询有管理权限的会议预订

        :raises: Error
        """
        mgr = MeetingReservationManager()
        if is_as_admin:
            mu = MeetingUserWrapper(user=operator)
            if not mu.is_admin():
                raise errors.AccessDenied(message=_('你没有管理员权限'))

            reservation = mgr.get_meeting_reservation_by_id(_id=reservation_id, select_for_update=False)
            if reservation is None:
                raise errors.TargetNotExist(message=_('会议预定记录不存在'))
        else:
            reservation = mgr.get_user_meeting_reservation(_id=reservation_id, user=operator)

        return reservation

    @classmethod
    def cancel_reservation(cls, reservation_id: str, operator: UserProfile, is_as_admin: bool) -> MeetingReservation:
        """
        取消会议预定

        :raises: Error
        """
        reservation = cls.get_has_perm_reservation(reservation_id, operator, is_as_admin)

        if reservation.status == MeetingReservation.Status.CANCELLED.value:
            return reservation

        cls._can_cancel_reservation(reservation=reservation)

        with transaction.atomic():
            obj = MeetingReservationManager.get_meeting_reservation_by_id(_id=reservation.id, select_for_update=True)
            cls._can_cancel_reservation(reservation=obj)

            update_fields = ['status', 'update_time']
            operate_status = None
            # 已为会议创建者预留会议室资源，先释放资源
            if reservation.room_reserve_status in [
                MeetingReservation.RoomReserveStatus.RESERVED.value,
                MeetingReservation.RoomReserveStatus.UNRELEASED.value
            ]:
                # 释放资源
                is_release_ok, release_desc = cls.tx_room_helper.tx_release_room_1(
                    tx_meeting_userid=reservation.tx_meeting_userid, room_type=reservation.room_type
                )
                if not is_release_ok:
                    raise errors.Error(message=_('释放会议室资源失败。') + release_desc)

                operate_status = MeetingReservationLog.OperateStatus.OK.value

                obj.room_reserve_status = MeetingReservation.RoomReserveStatus.RELEASED.value
                obj.room_reserve_desc = release_desc[0:254]
                update_fields += ['room_reserve_status', 'room_reserve_desc']

            # 更新为“已取消”状态
            obj.status = MeetingReservation.Status.CANCELLED.value
            obj.save(update_fields=update_fields)

        MeetingReservationManager.add_operate_log(content='取消会议预定', reservation_id=obj.id, operator=operator.username)
        if operate_status:
            MeetingReservationManager.add_room_reserve_log(
                operate_status=operate_status, content=release_desc,
                reservation_id=obj.id, operator=operator.username)

        return obj

    @staticmethod
    def _can_cancel_reservation(reservation: MeetingReservation):
        """
        会议预定是否可以取消
        :raises: Error
        """
        if reservation.status != MeetingReservation.Status.RESERVED.value:
            raise errors.ConflictError(message=_('不是“已预定”状态的会议预定记录'))

        now_ts = int(lib_time.time())
        if reservation.end_time <= now_ts:
            raise errors.ConflictError(message=_('已过会议预定结束时间'))

        # if reservation.start_time <= now_ts:
        #     raise errors.ConflictError(message=_('已进入会议预定时间'))
        #
        # if reservation.room_reserve_status == MeetingReservation.RoomReserveStatus.RESERVED.value:
        #     raise errors.ConflictError(message=_('已为会议创建者预留会议室资源'))
